package com.asialjim.wechat.spring.config.db;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.injector.methods.Insert;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.type.JdbcType;

import java.util.Objects;

import static java.util.stream.Collectors.joining;

/**
 * <h2><em>ASIAL JIM JAVA DOC</em></h2><hr/>
 * <h3>CLASS DESCRIPTION</h3><strong>
 * <p> 应用sql插入语句处理器
 * </strong><p><p><em> Copyright &copy; ztzh inc Ztzh Co., LTD</em><hr/>
 * @author Asial Jim &nbsp;&nbsp; Email: <a href="mailto:zengyz0128@zsmarter.com">ZSMARTER邮箱</a> &nbsp;&nbsp; <a href="mailto:asialjim@hotmail.com">HOTMAIL邮箱</a>
 * @since 2020/12/16 9:41 &nbsp; JDK 1.8
 * @version 1.0.0
 */
public class ApplicationInsert extends Insert {

    /**
     * <h4>METHOD DESCRIPTION</h4>
     * 注入自动生成的sql语句
     * @author Asial Jim &nbsp;&nbsp; Email: <a href="mailto:zengyz0128@zsmarter.com">ZSMARTER邮箱</a> &nbsp;&nbsp; <a href="mailto:asialjim@hotmail.com">HOTMAIL邮箱</a>
     * @since 2021/1/13 9:43
     */
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        KeyGenerator keyGenerator = new NoKeyGenerator();
        SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
        String columnScript = SqlScriptUtils.convertTrim(
                this.getAllInsertSqlColumnMaybeIf(tableInfo,null),
                LEFT_BRACKET,
                RIGHT_BRACKET,
                null,
                COMMA);

        String valuesScript = SqlScriptUtils.convertTrim(
                this.getAllInsertSqlPropertyMaybeIf(tableInfo,null),
                LEFT_BRACKET,
                RIGHT_BRACKET,
                null,
                COMMA);

        String keyProperty = null;
        String keyColumn = null;
        // 表包含主键处理逻辑,如果不包含主键当普通字段处理
        if (StringUtils.isNotBlank(tableInfo.getKeyProperty())) {
            if (tableInfo.getIdType() == IdType.AUTO) {
                /** 自增主键 */
                keyGenerator = new Jdbc3KeyGenerator();
                keyProperty = tableInfo.getKeyProperty();
                keyColumn = tableInfo.getKeyColumn();
            } else {
                if (null != tableInfo.getKeySequence()) {
                    keyGenerator = TableInfoHelper.genKeyGenerator(getMethod(sqlMethod), tableInfo, builderAssistant);
                    keyProperty = tableInfo.getKeyProperty();
                    keyColumn = tableInfo.getKeyColumn();
                }
            }
        }
        String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return this.addInsertMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource, keyGenerator, keyProperty, keyColumn);
    }

    /**
     * <h4>METHOD DESCRIPTION</h4>
     * 根据数据库实体获取insert语句的value属性部分的sql脚本，并使用if标签包裹
     * @param tableInfo {@link TableInfo 数据库表信息}
     * @param prefix {@link String 前缀}
     * @return {@link String sql脚本}
     * @author Asial Jim &nbsp;&nbsp; Email: <a href="mailto:zengyz0128@zsmarter.com">ZSMARTER邮箱</a> &nbsp;&nbsp; <a href="mailto:asialjim@hotmail.com">HOTMAIL邮箱</a>
     * @since 2021/1/13 9:45
     */
    public String getAllInsertSqlPropertyMaybeIf(TableInfo tableInfo,final String prefix) {
        final String newPrefix = prefix == null ? EMPTY : prefix;
        String keyInsertSqlProperty = tableInfo.getKeyInsertSqlProperty(newPrefix, true);
        String collection = tableInfo.getFieldList().stream().map(i -> this.insertPropertyScript(i,newPrefix)).filter(Objects::nonNull).collect(joining(NEWLINE));
        return keyInsertSqlProperty + collection;
    }

    /**
     * <h4>METHOD DESCRIPTION</h4>
     *  如果是自动填入date类型的字段，则填入sysdate，否则填入if包裹的包含条件测试的脚本
     * @param i {@link TableFieldInfo 数据库表字段信息}
     * @param newPrefix {@link String 前缀}
     * @return {@link String 单字段的sql脚本}
     * @author Asial Jim &nbsp;&nbsp; Email: <a href="mailto:zengyz0128@zsmarter.com">ZSMARTER邮箱</a> &nbsp;&nbsp; <a href="mailto:asialjim@hotmail.com">HOTMAIL邮箱</a>
     * @since 2021/1/13 9:47
     */
    public String insertPropertyScript(TableFieldInfo i,final String newPrefix){
        return i.isWithInsertFill() && i.getJdbcType() == JdbcType.DATE ? "sysdate," : i.getInsertSqlPropertyMaybeIf(newPrefix);
    }

    /**
     * <h4>METHOD DESCRIPTION</h4>
     * 获取表字段部分sql脚本，并使用if标签包裹
     * @param info {@link TableInfo 表信息}
     * @param prefix {@link String 前缀}
     * @return {@link String sql脚本}
     * @author Asial Jim &nbsp;&nbsp; Email: <a href="mailto:zengyz0128@zsmarter.com">ZSMARTER邮箱</a> &nbsp;&nbsp; <a href="mailto:asialjim@hotmail.com">HOTMAIL邮箱</a>
     * @since 2021/1/13 9:50
     */
    public String getAllInsertSqlColumnMaybeIf(TableInfo info,final String prefix) {
        final String newPrefix = prefix == null ? EMPTY : prefix;
        String keyInsertSqlColumn = info.getKeyInsertSqlColumn(true);
        String collection = info.getFieldList().stream().map(i -> this.insertColumnScript(i,newPrefix)).filter(Objects::nonNull).collect(joining(NEWLINE));
        return keyInsertSqlColumn + collection;
    }

    /**
     * <h4>METHOD DESCRIPTION</h4>
     *  如果是自动填入date类型字段，则直接获取数据库字段名,否则获取报摊if 条件测试的脚本
     * @param i {@link TableFieldInfo 数据库表字段信息}
     * @param newPrefix {@link String 前缀}
     * @return {@link String 单表字段sql脚本}
     * @author Asial Jim &nbsp;&nbsp; Email: <a href="mailto:zengyz0128@zsmarter.com">ZSMARTER邮箱</a> &nbsp;&nbsp; <a href="mailto:asialjim@hotmail.com">HOTMAIL邮箱</a>
     * @since 2021/1/13 9:52
     */
    private String insertColumnScript(TableFieldInfo i, final String newPrefix) {
        return i.isWithInsertFill() && i.getJdbcType() == JdbcType.DATE
                ? i.getInsertSqlColumn()
                : i.getInsertSqlColumnMaybeIf(newPrefix);
    }
}
